package com.jt.www.biz.pay.service.impl;

import com.jt.www.biz.pay.service.PayUrlInfoService;
import com.jt.www.dao.mapper.issue.mapper.IssuePolicyLogEntityMapper;
import com.jt.www.dao.mapper.issue.mapper.IssueRecordEntityMapper;
import com.jt.www.dao.mapper.woxuebao.PayUrlInfoMapper;
import com.jt.www.enums.issue.IssueEnum;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.issue.entity.IssueRecordEntity;
import com.jt.www.model.pay.ResBindDetailQo;
import com.jt.www.model.pay.ResBindQo;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.woxuebao.PayUrlInfoEntity;
import com.jt.www.remote.DexClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtil;
import com.jt.www.util.JsonUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.*;

@Service
public class PayUrlInfoServiceImpl implements PayUrlInfoService {

    public static final Logger log = LoggerFactory.getLogger(PayUrlInfoServiceImpl.class);
    @Autowired
    DexClient dexClient;
    @Autowired
    InsClient insClient;
    @Autowired
    private PayUrlInfoMapper payUrlInfoMapper;
    @Autowired
    private IssueRecordEntityMapper issueRecordEntityMapper;
    @Autowired
    private IssuePolicyLogEntityMapper issuePolicyLogEntityMapper;

    @Override
    public ResponseEntity queryPayUrl(String findCode, String appCode) {

        Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
        WeekendCriteria<PayUrlInfoEntity, Object> criteria = weekend.weekendCriteria();
        criteria.andEqualTo(PayUrlInfoEntity::getApplicationFormCode, appCode);
        criteria.andEqualTo(PayUrlInfoEntity::getIsDeleted, false);

        List<PayUrlInfoEntity> list = payUrlInfoMapper.selectByExample(weekend);

        if (list != null && list.size() > 0) {
            PayUrlInfoEntity vo = list.get(0);

            Map<String, Object> map = new HashMap<>();
            if (vo.getPayUrlStatus()) {
                map.put("applicationFormCode", appCode);
                map.put("payUrl", vo.getPayUrl());
                map.put("orderCoder",vo.getCpcNoticeNo());
            } else {
                map.put("applicationFormCode", appCode);
                map.put("payUrl", "");
                map.put("message", vo.getPayUrlMessage());
            }
            return GenericDataResponse.okWithData(map);
        }

        return GenericDataResponse.errorWithMsg("未查询到该投保单的支付地址信息");
    }

    @Override
    public void ynxpxIssueEffect(Integer times) {
        String findCode = "ynxpxIssueEffect_" + System.currentTimeMillis();
        try {
            log.info("{}云南学平险调用平安承保接口任务 开始执行", findCode);
            // 1.查询t_pay_url_info表中支付成功状态 and （1未出单 或 3出单失败） and 请求次数<times
            List<String> statusList = new ArrayList<String>();
            statusList.add("1");
            statusList.add("3");
            Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
            WeekendCriteria<PayUrlInfoEntity, Object> criteria = weekend.weekendCriteria();
            criteria.andEqualTo(PayUrlInfoEntity::getPayStatus, true);
            criteria.andIn(PayUrlInfoEntity::getIssueStatus, statusList);
            criteria.andLessThan(PayUrlInfoEntity::getIssueTimes, times);

            List<PayUrlInfoEntity> list = payUrlInfoMapper.selectByExample(weekend);
            log.info("{}云南学平险调用平安承保接口任务 记录数{}", findCode, list.size());
            if (list != null && list.size() > 0) {

                // 2.更新issue_status = 0(处理中)，times + 1
                list.forEach(e -> {

                    String seqNo = Long.toString(Math.abs(new Random().nextLong()));
                    String detailFindCode = findCode + "_" + seqNo;
                    log.info("{}云南学平险调用平安承保接口任务 applicationFormCode:{},applyPolicyNo:{},cpcNoticeNo:{}",
                            detailFindCode, e.getApplicationFormCode(), e.getApplyPolicyNo(), e.getCpcNoticeNo());

                    PayUrlInfoEntity updEntity = new PayUrlInfoEntity();
                    updEntity.setIssueStatus("0");
                    updEntity.setIssueTimes(e.getIssueTimes() + 1);
                    updEntity.setId(e.getId());
                    payUrlInfoMapper.updateByPrimaryKeySelective(updEntity);

                    //拼装报文
                    Document doc = DocumentHelper.createDocument();
                    Element info = doc.addElement("Message");
                    doc.setRootElement(info);
                    Element Head = info.addElement("Head");
                    Head.addElement("SerialNo").addText(seqNo);
                    Element Body = info.addElement("Body");
                    Element Policy = Body.addElement("Policy");
                    Policy.addElement("applicationFormCode").addText(e.getApplicationFormCode());
                    Policy.addElement("applyPolicyNo").addText(e.getApplyPolicyNo());
                    Policy.addElement("cpcNoticeNo").addText(e.getCpcNoticeNo());

                    log.info("{}云南学平险调用平安承保接口任务 调用数据交换中心报文{}", detailFindCode, info.asXML());

                    try {
                        // 3.调用数据交换中心
                        ResponseEntity<String> responseEntity = dexClient.text("edu", "20200312003", "1.0", seqNo, info.asXML());

                        String ebody = responseEntity.getBody();

                        Document document = DocumentHelper.parseText(ebody);
                        Element ebodyElement = document.getRootElement();
                        String code = ebodyElement.element("ResponseCode").getStringValue();

                        if ("SUCCESS".equals(code)) {
                            // 更新出单状态=2，保单号，更新时间
                            String policyNo = ebodyElement.element("PolicyNo").getStringValue();
                            PayUrlInfoEntity qo = new PayUrlInfoEntity();
                            qo.setId(e.getId());
                            qo.setIssueStatus("2");
                            qo.setPolicyNo(policyNo);
                            qo.setUpdateTime(DateUtils.getCurrentTime());

                            payUrlInfoMapper.updateByPrimaryKeySelective(qo);

                            log.info("{}云南学平险调用平安承保接口任务 调用数据交换中心返回保单号{}", detailFindCode, policyNo);

                            // 保存到t_issue_record表
                            IssueRecordEntity issueRecordEntity = new IssueRecordEntity();
                            issueRecordEntity.setApplicationFormCode(e.getApplicationFormCode());
                            List<IssueRecordEntity> select = issueRecordEntityMapper.select(issueRecordEntity);

                            issueRecordEntity.setPolicyNo(policyNo);
                            issueRecordEntity.setStatus("2");
                            issueRecordEntity.setSendStatus("2");
                            issueRecordEntity.setUpdateTime(DateUtils.getCurrentTime());

                            if (select != null && select.size() > 0) {
                                issueRecordEntity.setId(select.get(0).getId());
                                issueRecordEntityMapper.updateByPrimaryKeySelective(issueRecordEntity);
                                log.info("{} t_issue_record表更新记录完成 tbNo:{}", detailFindCode, e.getApplicationFormCode());
                            }

                            String ifCode = "20200312002";
                            String proCode = IssueEnum.getProCodeByIfCode(ifCode);
                            IssuePolicyLogEntity issuePolicyLogEntity = new IssuePolicyLogEntity();
                            String consumeStatus = "1";
                            issuePolicyLogEntity.setApplicationFormCode(e.getApplicationFormCode());
                            issuePolicyLogEntity.setPolicyNo(policyNo);
                            issuePolicyLogEntity.setType("1");//电子保单
                            issuePolicyLogEntity.setStatus(consumeStatus);
                            issuePolicyLogEntity.setCreateTime(DateUtils.getCurrentTime());
                            issuePolicyLogEntity.setUpdateTime(DateUtils.getCurrentTime());
                            issuePolicyLogEntity.setProCode(proCode);

                            // 云南学平险下载电子保单 组装报文  组装json 报文
                            Map<String, String> map = new HashMap<>();
                            map.put("partnerName", "P_JTJJKM_PE");
                            map.put("productClass", "03");
                            map.put("requestId", "StandardElectronicPolicyV2" + System.currentTimeMillis());
                            map.put("departmentCode", "21685");
                            map.put("name", e.getHolderName());
                            map.put("policyNo", policyNo);
                            map.put("certificateNo", e.getLicenseNo());
                            if ("cardType_0".equals(e.getLicenseType())) {
                                map.put("certificateType", "01");
                            } else if ("cardType_1".equals(e.getLicenseType())) {
                                map.put("certificateType", "02");
                            } else if ("cardType_17".equals(e.getLicenseType())) {
                                map.put("certificateType", "05");
                            }
                            String param = JsonUtils.toJson(map);

                            issuePolicyLogEntity.setParam(param);
                            issuePolicyLogEntity.setIfCode(ifCode);

                            //判断是否已经存在该投保单电子保单记录
                            Weekend<IssuePolicyLogEntity> issuePolicyLogWeekend = Weekend.of(IssuePolicyLogEntity.class);
                            WeekendCriteria<IssuePolicyLogEntity, Object> issuePolicyLogCriteria = issuePolicyLogWeekend.weekendCriteria();
                            issuePolicyLogCriteria.andEqualTo(IssuePolicyLogEntity::getApplicationFormCode, e.getApplicationFormCode());

                            List<IssuePolicyLogEntity> issuePolicyLogEntities = issuePolicyLogEntityMapper.selectByExample(issuePolicyLogWeekend);
                            if (issuePolicyLogEntities != null && issuePolicyLogEntities.size() > 0) {
                                issuePolicyLogEntity.setId(issuePolicyLogEntities.get(0).getId());
                                issuePolicyLogEntity.setTimes(issuePolicyLogEntities.get(0).getTimes());
                                issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                            } else {
                                issuePolicyLogEntity.setTimes(0);
                                issuePolicyLogEntityMapper.insert(issuePolicyLogEntity);
                            }

                            log.info("{}云南学平险调用平安电子保单接口任务 组装报文{}", detailFindCode, param);
                            String elecSeqNo = Long.toString(Math.abs(new Random().nextLong()));
                            ResponseEntity<String> elecResp = dexClient.text("edu", "20200312004", "1.0", elecSeqNo, param);

                            String elecbody = elecResp.getBody();
                            Document elecdoc = DocumentHelper.parseText(elecbody);
                            Element elecbodyElement = elecdoc.getRootElement();
                            Element elecdata = elecbodyElement.element("data");
                            String fileId = "";
                            if (elecdata == null || "".equals(elecdata)) {
                                consumeStatus = "3";
                                log.error("{} 调用平安电子保单接口任务 返回结果{}", detailFindCode, JsonUtils.toJson(elecbodyElement));
                            } else {
                                consumeStatus = "2";
                                fileId = elecdata.getStringValue();
                                // 下载电子保单成功，更新数据库，绑定资源
                                log.info("{} 调用平安电子保单接口任务 fileId ：{}", detailFindCode, fileId);
                            }
                            issuePolicyLogEntity.setStatus(consumeStatus);
                            bindingResources(detailFindCode, e.getApplicationFormCode(), fileId, issuePolicyLogEntity);

                        } else {
                            String msg = ebodyElement.element("ErrorMessage").getStringValue();
                            PayUrlInfoEntity qo = new PayUrlInfoEntity();
                            qo.setId(e.getId());
                            qo.setPolicyNoMessage(msg);
                            qo.setIssueStatus("3");
                            qo.setUpdateTime(DateUtils.getCurrentTime());

                            payUrlInfoMapper.updateByPrimaryKeySelective(qo);

                            // 保存到t_issue_record表
                            IssueRecordEntity issueRecordEntity = new IssueRecordEntity();
                            issueRecordEntity.setApplicationFormCode(e.getApplicationFormCode());
                            List<IssueRecordEntity> select = issueRecordEntityMapper.select(issueRecordEntity);

                            issueRecordEntity.setStatus("3");
                            issueRecordEntity.setSendStatus("1");
                            issueRecordEntity.setUpdateTime(DateUtils.getCurrentTime());

                            if (select != null && select.size() > 0) {
                                issueRecordEntity.setId(select.get(0).getId());
                                issueRecordEntityMapper.updateByPrimaryKeySelective(issueRecordEntity);
                                log.info("{} t_issue_record表更新记录完成 tbNo:{}", detailFindCode, e.getApplicationFormCode());
                            }
                        }

                        log.info("{}云南学平险调用平安承保接口任务 调用数据交换中心返回结果{}", detailFindCode, JsonUtil.object2Json(responseEntity));
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        log.info("{}云南学平险调用平安承保接口任务 e1异常{}", detailFindCode, e1);
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("{}云南学平险调用平安承保接口任务 e异常{}", findCode, e);
        }
    }

    /*
     * 绑定资源，更新下载状态
     * @param applicationFormCode 投保单号
     * @param fileId             文件id
     */
    private void bindingResources(String findCode, String applicationFormCode, String fileId, IssuePolicyLogEntity issuePolicyLogEntity) throws Exception {

        String consumeStatus = issuePolicyLogEntity.getStatus();
        log.info("{} 绑定电子保单 开始 applicationFormCode:{},fileId:{},consumeStatus:{}", findCode, applicationFormCode, fileId, consumeStatus);

        if ("3".equals(consumeStatus)) {
            issuePolicyLogEntity.setTimes(1);
            issuePolicyLogEntity.setEPolicyId(fileId);
            issuePolicyLogEntity.setStatus("3");
            issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
        } else {

            ResBindQo resBindQo = new ResBindQo();
            resBindQo.setApplicationFormCode(applicationFormCode);
            ResBindDetailQo resBindDetailQo = new ResBindDetailQo();
            resBindDetailQo.setBizCodeType("01");
            resBindDetailQo.setResCode("A002");
            resBindDetailQo.setResId(fileId);
            resBindDetailQo.setResName("电子保单、保单影印件");
            List<ResBindDetailQo> list = new ArrayList<>();
            list.add(resBindDetailQo);
            resBindQo.setDetailList(list);
            ResponseEntity<GenericListResponse<Map<String, String>>> genericListResponseResponseEntity = null;
            try {
                String s = JsonUtils.toJson(resBindQo);
                log.info("{} 调用绑定资源接口开始 投保单号:{},入参:{} ", findCode, applicationFormCode, s);
                genericListResponseResponseEntity = insClient.bindResources(resBindQo);
                GenericListResponse<Map<String, String>> body = genericListResponseResponseEntity.getBody();
                String code = body.getCode();
                if (!"0000".equals(code)) {
                    log.info("{} 绑定电子保单 失败 投保单号:{},code:{},msg:{}", findCode, applicationFormCode, body.getCode(), body.getMsg());

                    issuePolicyLogEntity.setTimes(1);
                    issuePolicyLogEntity.setEPolicyId(fileId);
                    issuePolicyLogEntity.setStatus("3");
                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);

                } else {
                    log.info("{} 绑定电子保单 成功 投保单号:{}, code:{},msg:{}", findCode, applicationFormCode, body.getCode(), body.getMsg());

                    issuePolicyLogEntity.setTimes(1);
                    issuePolicyLogEntity.setEPolicyId(fileId);
                    issuePolicyLogEntity.setStatus("2");
                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.info("{} 绑定电子保单 异常 {}", findCode, e);

                issuePolicyLogEntity.setTimes(1);
                issuePolicyLogEntity.setEPolicyId(fileId);
                issuePolicyLogEntity.setStatus("3");
                issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
            }
        }
    }
}
